package se.hexabit.imagebank.traverser

import java.io.File
import java.util.Properties
import com.drew.imaging.ImageMetadataReader
import com.drew.imaging.ImageProcessingException
import com.drew.metadata.Metadata
import com.drew.metadata.exif.ExifIFD0Directory
import com.drew.metadata.exif.ExifSubIFDDirectory
import se.hexabit.imagebank.Config
import java.util.Formatter.DateTime
import java.util.Formatter.DateTime
import java.util.Date
import java.io.IOException
import java.text.SimpleDateFormat
import java.text.DateFormat
import java.nio.file.Files
import java.nio.file.StandardCopyOption

class DirectoryTraverser {
  /*
   * TODO: Move to constructor
   */
  val p: Properties = Config.getInstance().readConfig(null)
  val fileTypes: Array[String] = p.getProperty("ib.file.types").split(",")
  val destRoot: String = p.getProperty("ib.dest.path");

  def traverse(root: File, sum: Int = 0): Int = {
    var hits: Int = sum

    if (root.canRead()) {
      val list: Array[File] = root.listFiles()

      for (f <- list) {
        if (f.isDirectory()) {
          hits = traverse(f, hits)
        } else {
          hits += sortFileByDate(f)
        }
      }
    }
    hits
  }

  def sortFileByDate(f: File): Int = {
    if (matchExtension(f)) {
      val metaData: Metadata = getMetadata(f)
      val dir: Date = extractDate(Option(metaData.getDirectory(classOf[ExifIFD0Directory])), Option(metaData.getDirectory(classOf[ExifSubIFDDirectory])), f)
      val dest: Option[File] = createDirectory(dir, destRoot, "yyyy_MM_dd")
      dest.foreach { x => copyFile(f, x) }
      1
    } else {
      0
    }
  }

  def matchExtension(f: File): Boolean = {
    val name: String = f.getName()
    if (name.contains(".")) {
      val ext: String = name.substring(name.lastIndexOf('.') + 1, name.length())
      if (fileTypes.contains(ext)) {
        true
      } else {
        false
      }
    } else {
      false
    }
  }

  def copyFile(file: File, dest: File) = {
    Files.copy(file.toPath(), dest.toPath().resolve(file.getName()), StandardCopyOption.COPY_ATTRIBUTES);
  }

  @throws(classOf[IOException])
  def getMetadata(f: File) = {
    try {
      ImageMetadataReader.readMetadata(f);
    } catch {
      case e: ImageProcessingException => throw new IOException("Could not read imaga meta data in file: " + f)
    }
  }

  @throws(classOf[IOException])
  def extractDate(ifD0: Option[ExifIFD0Directory], sub: Option[ExifSubIFDDirectory], f: File): Date = {
    var date: Date = null

    if (sub.isDefined) {
      date = sub.get.getDate(ExifSubIFDDirectory.TAG_DATETIME_ORIGINAL);
    }
    if (date == null && ifD0.isDefined) {
      date = ifD0.get.getDate(ExifIFD0Directory.TAG_DATETIME);
    }

    if (date == null) {
      throw new IOException("Could not read date in file: " + f)
    }
    date
  }

  def createDirectory(dirName: Date, dest: String, format: String): Option[File] = {
    val df: DateFormat = new SimpleDateFormat(format);
    val fullName = dest + "/" + df.format(dirName)
    val dir: File = new File(fullName)
    if (dir.exists()) Option(dir)
    else if (dir.mkdirs()) Option(dir)
    else None
  }
}
